#include "notify_filter.h"

#include <string>
#include <sstream>

#include "base/logging.h"
#include "base/config_reader.h"
#include "redis_executor/redis_executor.h"
#include "redis_executor/simple_redis_locator.h"
#include "redis_executor/scoped_reply.h"

namespace imserver{

std::string GetDailyKey(time_t t) {
  struct tm tms;
  localtime_r(&t, &tms);
  std::ostringstream res;
  // Expires: Mon, 26 Jul 1997 05:00:00 GMT
  res << tms.tm_year + 1900;
  if (tms.tm_mon < 10) {
    res << '0';
  }
  res << tms.tm_mon;
  if (tms.tm_mday < 10) {
    res << '0';
  }
  res << tms.tm_mday;
  return res.str();
}

NotifyFilter::NotifyFilter() : redis_exec_(NULL) {
  ConfigReader cfg("../conf/bang_robot_service.conf");
  if (!cfg) {
    std::cerr << "Config file read error!" << std::endl;
    exit(1);
    return;
  }

  RedisLocator * locator = new FixedLocator(cfg.Get("redis", "server_list"));
  redis_exec_ = new RedisExecutor(locator);
}

int NotifyFilter::MostRecentBombed(int64_t uid) {
  const int MAX_BUF_LEN = 256;
  char cmd_buf[MAX_BUF_LEN];
  cmd_buf[MAX_BUF_LEN - 1] = '\0';
  snprintf(cmd_buf, MAX_BUF_LEN - 1, "GET im:userbombed:%lld", uid);

  ScopedReply reply(redis_exec_->Execute("", cmd_buf));
  if (reply) {
    if (reply->type == REDIS_REPLY_STRING) {
      LOG_INFO("redis MostRecentBombed=1, uid=" << uid);
      return 1;
    }
  } else {
    LOG_WARN("redis get MostRecentBombed err:" << cmd_buf);
    return -1;
  }

  LOG_INFO("redis MostRecentBombed=0, uid=" << uid);

  snprintf(cmd_buf, MAX_BUF_LEN - 1, "SETEX im:userbombed:%lld 864000 1", uid); // 10天有效
  for(int i = 0; i < 2; ++i) {
    ScopedReply reply(redis_exec_->Execute("", cmd_buf));
    if (reply) {
      LOG_INFO("redis set MostRecentBombed ok:" << cmd_buf);
      return 0;
    }
  }

  LOG_WARN("redis set MostRecentBombed error:" << cmd_buf);
  return -1;
}


int NotifyFilter::MostRecentTalked(int64_t shop_client, int64_t shop_keeper/*reciver*/) {
  redisContext * context = redis_exec_->AllocContext("");
  if (context == NULL) {
    LOG_WARN("MostRecentTalked redis connect err " << shop_keeper);
    return -1;
  }
  time_t now = time(NULL);
  std::string yesterday = GetDailyKey(now - 86400);
  std::string today = GetDailyKey(now);


  redisAppendCommand(context, "SISMEMBER im:daily_contacted:%lld:%s %lld", shop_keeper, yesterday.c_str(), shop_client);
  redisAppendCommand(context, "SISMEMBER im:daily_contacted:%lld:%s %lld", shop_keeper, today.c_str(), shop_client);
  LOG_DEBUG("SISMEMBER im:daily_contacted:" << ":" << shop_keeper << ":" << today << " " << shop_client);

  redisReply *reply = NULL;
  int talked = 0;
  for(int i = 0; i < 2; ++i) {
    int rcode = redisGetReply(context, (void **)&reply);
    if (rcode != REDIS_OK || reply == NULL || reply->type != REDIS_REPLY_INTEGER) {
      talked = -1;
      LOG_WARN("MostRecentTalked redis SISMEMBER err " << shop_keeper);
      break;
    }
    if (reply->integer) {
      talked = 1;
    } else {
      if (i == 1) {
        redisAppendCommand(context, "SADD im:daily_contacted:%lld:%s %lld", shop_keeper, today.c_str(), shop_client);
        LOG_DEBUG("SADD im:daily_contacted:" << ":" << shop_keeper << ":" << today << " " << shop_client);
        redisAppendCommand(context, "EXPIRE im:daily_contacted:%lld:%s 172800", shop_keeper, today.c_str()); //两天超时
        // redisAppendCommand(context, "EXPIRE im:daily_contacted:%lld:%s 300", shop_keeper, today.c_str()); //5分钟超时,仅供测试
        redisReply * add_reply = NULL;
        for(int j = 0; j < 2; ++j) {
          int rc = redisGetReply(context, (void **)&add_reply);
          if (rc != REDIS_OK || add_reply == NULL) {
            talked = -2;
            LOG_WARN("MostRecentTalked redis SADD err " << shop_keeper);
            break;
          }
          freeReplyObject(add_reply);
          add_reply = NULL;
        }
      }
    }

    freeReplyObject(reply);
    reply = NULL;
  }

  redis_exec_->ReleaseContext("", context, talked >= 0);

  LOG_DEBUG("MostRecentTalked shop_client=" << shop_client << " shop_keeper=" << shop_keeper << " " << talked);
  return talked;
}

}

